using System;
using System.Security.Policy;
using System.Collections;

namespace Crawler
{
	/// <summary>
	/// understands the storage or url stack 
	/// </summary>
	public class UrlStack : IUrlStack
	{
		protected Hashtable hashList;
		protected Queue queueList;
		private int notificationCount = 0;
		private ICrawlerContext crawlerContext;
		public event UrlAddedToUrlStackHandler UrlAddedToUrlStack;

		public UrlStack(Crawler.ICrawlerContext crawlerContext)
		{
			this.hashList = new Hashtable();
			this.queueList = new Queue();
			this.crawlerContext = crawlerContext ;
		}
		
		public virtual void Add(Url Key, bool triggerFetcher)
		{
			String UrlStr = new String(Key.Value.ToCharArray());
			try{
				this.hashList.Add(Key, UrlStr);
				this.queueList.Enqueue(Key);
				if(triggerFetcher) {
					OnUrlAddedToUrlStack(new UrlAddedToUrlStackArgs());	 
				}
			}catch(ArgumentException keyAlreadyExists){}
		}

		public void TriggerNotifications()
		{
			while(queueList.Count>1)
			{
				crawlerContext.UrlStackEmpty = false; 
				OnUrlAddedToUrlStack(new UrlAddedToUrlStackArgs());
			}
			crawlerContext.UrlStackEmpty = true; 
			OnUrlAddedToUrlStack(new UrlAddedToUrlStackArgs());
		}
		
		public virtual bool HasNext() {
			return queueList.Count > 0;
		}

		public virtual Url GetNext()
		{
			Url returnVal=new Url("http://xilun");
			if(queueList.Count > 0)
			{
				returnVal = (Url)this.queueList.Peek();
			}
			this.Remove();
			
			return returnVal;
		}

		public virtual bool IsPresent(Url Key)
		{
			return hashList.Contains(Key);
		}

		public virtual int Count
		{
			get
			{
				return queueList.Count;
			}
		}

		protected virtual void Remove()
		{
			Url Key = (Url)this.queueList.Dequeue();
			//this.hashList.Remove(Key);
		}

		protected virtual void OnUrlAddedToUrlStack(UrlAddedToUrlStackArgs args)
		{
			if (UrlAddedToUrlStack != null)
				UrlAddedToUrlStack(this, args);
		}
	}

	/// <summary>
	/// The delegate method provides a framework to handle the events that have been raised by the UrlStack
	/// </summary>
	public delegate void UrlAddedToUrlStackHandler(object sender, UrlAddedToUrlStackArgs args);

}
